package com.ch.mobilesha.img;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.ch.mobilesha.base.MobileShaApplication;

/**
 * 图片缓存（图片存放在sdcard上）
 * @author liuweixiang
 *
 */
public class PictureCache extends AbstractCache<String, Bitmap> {
	
	private static final int SOFT_CACHE_CAPACITY = 20;
    private static final int Hard_CACHE_CAPACITY = 40;
    
	public PictureCache(String dirName) {
		super(dirName);
		cache = new LinkedHashMap<String, Bitmap>(Hard_CACHE_CAPACITY / 2, 0.75f, true) {
			private static final long serialVersionUID = -7190622541619388252L;
			@Override
	        protected boolean removeEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) {
	            if (size() > Hard_CACHE_CAPACITY) {
	            	softCache.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
	                return true;
	            } else {
	                return false;
	            }
	        }
		};
		enableDiskCache(MobileShaApplication.getSelf(), AbstractCache.DISK_CACHE_SDCARD);
	}

	@Override
	public synchronized boolean containsKey(Object key) {
		boolean contains = super.containsKey(key);
		if(!contains)
			return softCache.containsKey(key) && softCache.get(key).get() != null;
		return contains;
	}

	@Override
	public synchronized Bitmap remove(Object key) {
		softCache.remove(key);
		return super.remove(key);
	}

	@Override
	public synchronized Bitmap get(Object elementKey) {
		Bitmap bitmap = super.get(elementKey);
		if (bitmap != null) {
			cache.remove(elementKey);
			cache.put((String) elementKey, bitmap);
            return bitmap;
        } 
		 
		SoftReference<Bitmap> reference = softCache.get(elementKey);
        if (reference != null) {
            bitmap = reference.get();
            if (bitmap != null) {
            	cache.put((String) elementKey, bitmap);
            	softCache.remove(elementKey);
                return bitmap;
            } else {
            	softCache.remove(elementKey);
            }
        }
        return bitmap;
	}

	@Override
	public void clearMemoryCache() {
		super.clearMemoryCache();
		softCache.clear();
	}

	private final static ConcurrentHashMap<String, SoftReference<Bitmap>> softCache =
        new ConcurrentHashMap<String, SoftReference<Bitmap>>(SOFT_CACHE_CAPACITY);
	
	@Override
	public String getFileNameForKey(String key) {
		return key.hashCode() + "";
	}

	@Override
	protected Bitmap readCacheFromDisk(String key) throws IOException {
		File file = getFileForKey(key); 
		
    	if (!file.exists()){
    		// 没找到缓存对应的文件
    		return null;
    	}
    	ObjectInputStream istream = new ObjectInputStream(new FileInputStream(file));
    	byte[] imageData;
		try {
			imageData = (byte[])istream.readObject();
		} catch (ClassNotFoundException e) {
			file.delete();
			e.printStackTrace();
			return null;
		}
        istream.close();
        return BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
	}

	@Override
	protected void writeValueToDisk(ObjectOutputStream ostream, Bitmap value) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();     
		value.compress(Bitmap.CompressFormat.PNG, 100, baos);     
		ostream.writeObject(baos.toByteArray());
	}

}
